package demo.pattern.singleton;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class EnumStarvingSingleton {
    private EnumStarvingSingleton(){}
    public static EnumStarvingSingleton getInstance(){
        return ContainerHolder.HOLDER.instance;
    }

    // 利用枚举类阻挡反射、序列化机制来创建对象，是最安全的单例实现方式；保证创建EnumStarvingSingleton对象只有1个
    private enum ContainerHolder{
        HOLDER;
        private EnumStarvingSingleton instance;
        ContainerHolder(){
            instance = new EnumStarvingSingleton();
        }
    }
	/**
	 * 总结：以上的代码通过反编译可以知道以下信息（反编译工具jad）
	 * （1）枚举类ContainerHolder是一个public static final 修饰的、extends Enum的普通类
	 * （2）枚举类的HOLDER实例在枚举类被加载的时候就被创建
	 * （3）创建的时候调用的是无参构造方法，ContainerHolder()
	 * （4）因此instance实例也被创建出来，所以枚举类型实现单例是“饿汉模式”
	 * （5）但是无法通过获取枚举类的构造函数ContainerHolder来创建新的EnumStarvingSingleton对象，从而破坏单例
	 */
	public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
		System.out.println(EnumStarvingSingleton.getInstance());
		System.out.println(EnumStarvingSingleton.getInstance());
		// 可以发现，通过内部枚举持有单例对象，防止反射通过构造函数创建新的对象。
		Class clazz = EnumStarvingSingleton.class;
		Constructor constructor = clazz.getDeclaredConstructor();
		constructor.setAccessible(true);
		EnumStarvingSingleton enumStarvingSingleton = (EnumStarvingSingleton)constructor.newInstance();
		System.out.println(enumStarvingSingleton.getInstance());
	}
}
